package com.rivulet.doj_backend.judger.judge1_0;

import com.rivulet.doj_backend.pojo.JudgeCode;

import java.io.*;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.List;
import java.util.logging.Filter;

import org.mozilla.universalchardet.UniversalDetector;

/**
 * {一句话形容此class功能}
 *
 * @author xujiac
 * @create 2021/4/27
 * @since 1.0.0
 */
public class JudgeNumOne {
    public static String fileName = "D:\\doj_workspace";

    //第一版本的设计

    /**
     * 通过执行一个外部进程（如命令行命令或程序）并捕获其输出时
     *
     * 通过附带的环境对代码进行编译并得到输出
     */
    public void judge(Integer user_id, String code, String languageType, List<JudgeCode> list) {
        checkFileName(user_id.toString());
        creatFile();
        File file = creatCodeFile(code, languageType);
        String encode = detectEncoding(file);
        System.out.println(encode);
        System.out.println(Charset.defaultCharset());
        String[] command = chooseCommand(languageType);
        try {
            for (int i = 0; i < 5; i++) {
                Date beginTime = new Date();
                Process process = Runtime.getRuntime().exec(command, null, new File(fileName));
                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
                writer.write(list.get(i).getWriterParam());
                writer.close();
                SequenceInputStream allInputStream = new SequenceInputStream(process.getInputStream(), process.getErrorStream());
                InputStreamReader reader = new InputStreamReader(allInputStream, "gbk");
                BufferedReader bufferedReader = new BufferedReader(reader);
                String res = "";
                StringBuilder str = new StringBuilder();
                while ((res = bufferedReader.readLine()) != null) {
                    System.out.println(res);
                    str.append(res + "\n");
                }
                bufferedReader.close();
                process.waitFor();
                process.destroy();
                Date endTime = new Date();
                long time = endTime.getTime() - beginTime.getTime();
                list.get(i).setReader(str.toString());
                list.get(i).setRunningTime((int) time);
            }
        } catch (Exception e) {
            System.out.println(e);
        } finally {
            //deleteDir(new File(fileName));
        }
    }

    public static String detectEncoding(File file) {
        try {
            InputStream fis = new FileInputStream(file);
            UniversalDetector detector = new UniversalDetector(null);
            byte[] buf = new byte[4096];
            int nread;
            while ((nread = fis.read(buf)) > 0 && !detector.isDone()) {
                detector.handleData(buf, 0, nread);
            }
            detector.dataEnd();
            String encoding = detector.getDetectedCharset();
            detector.reset();
            fis.close();
            return encoding;
        } catch (Exception e) {
            Charset defaultCharset = Charset.defaultCharset();
            return String.valueOf(defaultCharset);
        }
    }

    private String[] chooseCommand(String languageType) {
        if (languageType.equals("java")) {
            return new String[]{"cmd", "/c", "java Main.java"};
        } else if (languageType.equals("cpp")) {
            creatBatFile();
            return new String[]{"cmd", "/c", "cpp.bat"};
        } else if (languageType.equals("py")) {
            return new String[]{"cmd", "/c", "Python Main.py"};
        } else {
            return null;
        }
    }

    private File creatCodeFile(String code, String languageType) {
        File file = new File(fileName + File.separator + "Main." + languageType);
        try {
            if (!file.exists()) {
                file.createNewFile();
                BufferedWriter writer = new BufferedWriter(new FileWriter(file));
                writer.write(code);
                writer.close();
            }
        } catch (Exception e) {
            System.out.println(e);
        }
        return file;
    }

    private void creatBatFile() {
        File file = new File(fileName + File.separator + "cpp.bat");
        try {
            if (file.exists()) {
                BufferedWriter writer = new BufferedWriter(new FileWriter(file));
                String cppBat = "@echo off\n" +
                        "g++ -o main Main.cpp\n" +
                        "Main.exe";
                System.out.println(cppBat);
                writer.write(cppBat);
                writer.close();
            } else {
                file.createNewFile();
                BufferedWriter writer = new BufferedWriter(new FileWriter(file));
                String cppBat = "@echo off\n" +
                        "g++ -o main Main.cpp\n" +
                        "Main.exe";
                System.out.println(cppBat);
                writer.write(cppBat);
                writer.close();
            }
        } catch (IOException e) {
            System.out.println(e);
        }
    }

    private void creatFile() {
        File file = new File(fileName);
        if (file.exists()) {
            return;
        } else {
            file.mkdir();
        }
    }

    private void checkFileName(String user_id) {
        fileName = fileName + File.separator + user_id;
    }

    private static void deleteDir(File file) {
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (int i = 0; i < files.length; i++) {
                deleteDir(files[i]);
            }
        }
        file.delete();
    }
}
